/*
 * 此文件为项目底层代码
 * 定义了一些底层数据以及一些底层函数
 */
#include "basecode.h"

QString g_sAppName = "";

bool g_bIndependent = false;

QString g_sInitQSSPath;

bool g_bConnectSucceedRemind = false;
bool g_bConnectFailRemind = true;
bool g_bDisconnectRemind = false;
bool g_bAccidentDisconnectRemind = true;

unsigned int g_unSerialPortReadnums = 0;
unsigned int g_unSerialPortSendnums = 0;
unsigned int g_unTCPServerReadnums = 0;
unsigned int g_unTCPServerSendnums = 0;
unsigned int g_unTCPClientReadnums = 0;
unsigned int g_unTCPClientSendnums = 0;

bool g_bSerialPortAutoConnect = false;
QString g_sSerialPortConnectName;
int g_nSerialPortBaudIndex = 0;
int g_nSerialPortDataIndex = 0;
int g_nSerialPortControlIndex = 0;
int g_nSerialPortParityIndex = 0;
int g_nSerialPortStopIndex = 0;
unsigned int g_unSerialPortReadDataLimit = 0;
bool g_bSerialPortDataAutoClear = false;
unsigned int g_unSerialPortHistoryDatanumsLimit = 0;
TextFormat g_emSerialPortReadTextFormat = Local;
TextFormat g_emSerialPortSendTextFormat = Local;
bool g_bSerialPortConTrueRemind = false;
bool g_bSerialPortConFalseRemind = false;
bool g_bSerialPortDisconTrueRemind = false;
bool g_bSerialPortDisconRemind = true;

bool g_bTCPServerAutoListen = false;
QString g_sTCPServerListenIP;
quint16 g_un16TCPServerListenPort = 0;
unsigned int g_unTCPServerReadDataLimit = 0;
bool g_bTCPServerDataAutoClear = 0;
unsigned int g_unTCPServerHistoryDatanumsLimit = 0;
TextFormat g_emTCPServerReadTextFormat = Local;
TextFormat g_emTCPServerSendTextFormat = Local;

bool g_bTCPClientAutoConnect = false;
QString g_sTCPClientConnectIP;
quint16 g_un16TCPClientConnectPort = 0;
unsigned int g_unTCPClientReadDataLimit = 0;
bool g_bTCPClientDataAutoClear = 0;
unsigned int g_unTCPClientHistoryDatanumsLimit = 0;
TextFormat g_emTCPClientReadTextFormat = Local;
TextFormat g_emTCPClientSendTextFormat = Local;

bool g_bAutoSaveSettings = true;

///
/// \brief 检查是否有相同名称进程运行
/// \return
///
bool CheckRepeatProcess()
{
    QString input;
#if defined (Q_OS_LINUX)
    input = QString("ps -A");
#elif defined (Q_OS_WIN)
    input = QString("tasklist");
#else
    return false;
#endif
    QProcess *cmd = new QProcess();
    int nums = 0;
    cmd->start(input);
    QString processname1 = QString("DanpeCommDubugAssist");
    QString processname2 = qAppName();

    QString output;
    QString outstr;
    int findok;
    do
    {
        cmd->waitForReadyRead();
        outstr = QString::fromLocal8Bit(cmd->readAllStandardOutput());
        output.append(outstr);
    }
    while(!outstr.isEmpty());
    findok = output.indexOf(processname1);
    if (findok >= 0)
    {
        nums++;
        QString outp = output.mid(findok+1);
        findok = outp.indexOf(processname1);
        if (findok >= 0)
        {
            nums++;
        }
    }
    if (processname2 != processname1)
    {
        findok = output.indexOf(processname2);
        if (findok >= 0)
        {
            nums++;
            QString outp = output.mid(findok+1);
            findok = outp.indexOf(processname2);
            if (findok >= 0)
            {
                nums++;
            }
        }
    }
    cmd->kill();
    delete cmd;
    cmd = nullptr;
    if (nums > 1)
    {
        return true;
    }
    return false;
}

/***********************************************
 * 由文件完整路径得到文件所在目录路径
 ***********************************************/
QString PathxtoPath(QString pathx)
{
    QString name = pathx, path0;
    do
    {
        path0 = name;
        name = path0.section('/', 1);
    }
    while(!name.isEmpty());
    QString pat = pathx.remove("/" + path0);
    return pat;
}

/***********************************************
 * 检查文件路径是否存在
 ***********************************************/
bool CheckAndEstablishFiles(QString path)
{
    QDir dir;
    if (!dir.exists(path))
    {
        bool isOK = dir.mkpath(path);
        return isOK;
    }
    return true;
}

///
/// \brief 判断QString字符串是否可以转为Hex数据
/// \param data
/// \return
///
bool toHex(QString data)
{
    data = data.remove(' ');
    if (data.left(2) == "0x" || data.left(2) == "0X")  // 查看是否有前缀
    {
        data = data.mid(2);
    }
    bool isOK = true;
    for (int i = 0; i < data.length(); i++)
    {
        char outchar;
        isOK = toHex(data.at(i).toLatin1(), outchar);
        if (isOK == false)
        {
            return false;
        }
    }
    return true;
}

///
/// \brief 单字节判断是否可以转为Hex数据并输出Hex数据
/// \param data
/// \param outdata
/// \return
///
bool toHex(char data, char &outdata)
{
    outdata = data;
    bool success = true;
    if (data >= '0' && data <= '9')
    {
        outdata = data - 0x30;
    }
    else if (data >= 'A' && data <= 'F')
    {
        outdata = data - 'A' + 10;
    }
    else if (data >= 'a' && data <='f')
    {
        outdata = data - 'a' + 10;
    }
    else
    {
        success = false;
    }
    return success;
}

///
/// \brief 延时
/// \param msec
///
void MySleep(unsigned int msec)
{
    if (msec == 0)
    {
        return ;
    }
    QTime reachTime = QTime::currentTime().addMSecs(static_cast<int>(msec));
    while (QTime::currentTime() < reachTime)
        QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
}

///
/// \brief 字符串转HEX打印输出
/// \param str
/// \return
///
QString OUT_HEX_String(QByteArray str)
{
    QByteArray bytestr = str;
    const char *recvBuffer = bytestr.data();

    QString Hexdata;
    //qDebug() << "tcp client read hex length:" << readdata.length();
    for (int i = 0; i < bytestr.length(); i++)
    {
        Hexdata += QString("%1 ").arg(recvBuffer[i], 2, 16, QChar('0')).toUpper().remove("FFFFFFFFFFFFFF");
        //qDebug() << "Hexdata[" << i << "]: " << Hexdata;
    }
    Hexdata.chop(1);  // 删除末尾空格
    return Hexdata;
}

///
/// \brief TextFormat枚举转成字符串输出
/// \param format
/// \return
///
QString TextFormat2Str(TextFormat format)
{
    QString ret = "";
    switch (format) {
    case Local: ret = "Local"; break;
    case GBK: ret = "GBK"; break;
    case UTF8: ret = "UTF8"; break;
    case Unicode: ret = "Unicode"; break;
    case HEX: ret = "HEX"; break;
    }
    return ret;
}

TextFormat Str2TextFormat(QString str)
{
    TextFormat format = Local;
    if (str == "Hex" || str == "HEX")
    {
        format = HEX;
    }
    else if (str == "Local")
    {
        format = Local;
    }
    else if (str == "GBK")
    {
        format = GBK;
    }
    else if (str == "Unicode")
    {
        format = Unicode;
    }
    else if (str == "UTF8")
    {
        format = UTF8;
    }
    else {
        format = Local;
    }
    return format;
}

///
/// \brief utf8转GBK
/// \param strUtf8
/// \return
///
QByteArray utf8ToGBK(QByteArray strUtf8)
{
    QTextCodec *utf8Codec = QTextCodec::codecForName("utf-8");
    QTextCodec *gbkCodec = QTextCodec::codecForName("GBK");
    QString strunicode = utf8Codec->toUnicode(strUtf8.toStdString().data());
    QByteArray byteGbK = gbkCodec->fromUnicode(strunicode);
    return byteGbK;
}

QByteArray GBK2utf8(QByteArray strgbk)
{

    QTextCodec *gbk = QTextCodec::codecForName("gbk");
    QTextCodec *utf8 = QTextCodec::codecForName("UTF-8");

    char *p = strgbk.data();
    QString str = gbk->toUnicode(p);

    QByteArray utf8_bytes=utf8->fromUnicode(str);
    //p = utf8_bytes.data();
    //str = p;

    qDebug() << "gbk2utf8: " << utf8_bytes;

    return utf8_bytes;


//    QTextCodec *utf8Codec = QTextCodec::codecForName("utf-8");
//    QTextCodec *gbkCodec = QTextCodec::codecForName("GBK");
//    QString strunicode = gbkCodec->toUnicode(strgbk.toStdString().data());
//    QByteArray byteutf8 = utf8Codec->fromUnicode(strunicode);
//    return byteutf8;
}

///
/// \brief utf8转为Unicode
/// \param strutf8
/// \return
///
QByteArray utf8ToUnicode(QByteArray strutf8)
{
    //qDebug() << "uft8:" << OUT_HEX_String(strutf8);
    QTextCodec *utf8Codec = QTextCodec::codecForName("utf-8");
    QString strunicode = utf8Codec->toUnicode(strutf8.toStdString().data());
    int length = strunicode.length();
    QChar *datas = strunicode.data();
    char cdatas[length * 2];
    for (int i = 0; i < length; i++)
    {
        cdatas[i * 2] = (datas[i].unicode() >> 8) & 0xff;
        cdatas[i * 2 + 1] = datas[i].unicode() & 0xff;
    }
    QByteArray bytedatas = QByteArray::fromRawData(cdatas, length * 2);
    return bytedatas.data();
}

QByteArray unicodeToUtf8(const QString &unicode)
{
    QString result;
    int index = unicode.indexOf("\\u");
    while (index != -1)
    {
        QString s1 = unicode.mid(index + 2, 4);
        result.append(s1.toUShort(0, 16));
        index = unicode.indexOf("\\u", index+5);
    }
    return result.toUtf8().constData();

}
